home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 February: Tool Chest / Dev.CD Feb 94.toast / New System Software Extensions / QuickDraw™ GX v1.0ß2 / Sample Code / Printing Samples / Printer Drivers… / Printer Status Routines < prev   
Encoding:
Text File  |  1993-09-14  |  16.5 KB  |  600 lines  |  [TEXT/MPS ]

  1. /*____________________________________________________
  2.  
  3.     Sample routines for sending status to the desktop
  4.     printer window, and handling user alerts.
  5.  
  6.                    Apple Computer, Inc.
  7.                   Copyright ©1991 - 1993
  8.  
  9.         9/13/93 - dmh - Updated for the b2 seed.
  10.  
  11.     Note:  Descriptions are listed in the "Mark" menu.
  12.  
  13.     ___________________________________________________    */
  14.  
  15.  
  16. // Sample code for writing status to the desktop printer window.
  17.  
  18.  
  19. #define    kTransmissionStatID                1
  20. #define    kOpeningConnectionStatIdx        8
  21.  
  22.  
  23.     anErr = GXReportStatus(kTransmissionStatID, kOpeningConnectionStatIdx);
  24.     
  25.  
  26. resource 'stat' (kTransmissionStatID, sysheap, purgeable)
  27. {
  28.     kDrvrCreatorType,
  29.     {
  30.         informationalStatus,        0,                                    kNoAlertCoolID,                "Sending part of the page…";
  31.         informationalStatus,        0,                                    kNoAlertCoolID,                "Preparing part of the page…";
  32.         userAlert,                     kChangeCarouselsDlogID,     kNoAlertCoolID,                "Please load the appropriate pen.";
  33.         informationalStatus,     0,                                 kNoAlertCoolID,                "A print test is in progress.  Please wait…";
  34.         userAlert,                     0,                                    kBadTonerCartridgeCoolID,    "The toner cartridge is improperly loaded.";
  35.         informationalStatus,     0,                                    kNoAlertCoolID,                "Printing the page.";
  36.         userAlert,                     0,                                    kCantFindPrinterCoolID,        "Trying to locate the printer…";
  37.         openConnectionStatus,     0,                                    kNoAlertCoolID,                "Opening a connection to the printer…";
  38.     }
  39. };
  40.  
  41.  
  42.  
  43. //        Alerts GX already handles -
  44. //
  45. //            manual feed
  46. //            paper jam
  47. //            failed to print
  48. //            printer ready
  49. //            out of paper
  50. //            no paper tray
  51. //            alert me before printing
  52. //            alert me after printing
  53. //
  54. //        PrintingDrivers.h has constants you need for this    
  55.  
  56.  
  57.  
  58. //    Sample code for "Manual Feed Alert" - one that we help you with
  59.  
  60. //
  61. //
  62. //        DoManualFeedDialog
  63. //
  64. //        This function will present a manual feed dialog to the user.  In this
  65. //        example we have a printer that is smart enough to know if the user has
  66. //        placed paper in the manual feed slot.  This printer will also allow the
  67. //        user to decide to switch to automatic feed at dialog time.
  68. //
  69. //        The driver must allocate a status record with a buffer that will contain
  70. //        the gxManualFeedRecord.  This record contains the name of the papertype
  71. //        which needs to be fed.  This will be displayed in the dialog.  The record
  72. //        also contains a boolean that tells the printing manager whether the dialog should 
  73. //        contain the automatic feed button.
  74. //
  75. //        The driver fills in the statResId and statResIndex fields of the status record
  76. //        to indicate that the desired stat resource belongs to the universal driver and
  77. //        the particular alert is for manual feed.  The papertype name is filled in.
  78. //
  79. //        The driver then calls GXAlertTheUser which will display the dialog.  The driver
  80. //        continues to call GXAlertTheUser until an error is returned or the user selects
  81. //        one of the buttons in the dialog ( ok, cancel or autoFeed ).  Because this printer
  82. //        is so smart, it can tell if the user fed paper without having the user select
  83. //        any button.  The driver checks for this case in the loop.  If this case is detected,
  84. //        the driver makes a last call to GXAlertTheUser to tell the Printing Manager to
  85. //        remove the dialog.  Once the user selects any button in the dialog, the dialog
  86. //        is automatically dismissed. The dialog is also dismissed when any error is returned.
  87. //
  88. //        The driver examines the dialogResult field of the status record to see which
  89. //        option the user has selected.
  90. //
  91. //        Before exiting the routine, the status record pointer is disposed.
  92. //
  93. //        Note that the CheckToSeeIfPaperWasFed routine must be supplied by the driver.
  94. //
  95. //
  96.  
  97.  
  98. OSErr    DoManualFeedDialog()
  99. {
  100.     OSErr                anErr;
  101.     gxStatusRecord    *pStatus;    
  102.     
  103. // allocate the status record
  104.  
  105.     pStatus = (Ptr) NewPtrClear(sizeof(gxStatusRecord) + gxManualFeedStatusBufferSize);
  106.     anErr = MemError();
  107.  
  108.     if (anErr == noErr ) {
  109.  
  110.         gxManualFeedRecord    *mfeedInfo;
  111.  
  112.         pStatus->statResId         = gxUnivAlertStatusResourceId;
  113.         pStatus->statResIndex     = gxUnivManualFeedIndex;
  114.         pStatus->bufferLen        = gxManualFeedStatusBufferSize;
  115.  
  116.         mfeedInfo = (gxManualFeedRecord *) &pStatus->statusBuffer;
  117.         mfeedInfo->canAutoFeed = true;
  118.         GXGetPaperTypeName(thePaperType, mfeedInfo->paperTypeName);
  119.  
  120.  
  121. // Tell the Printing Manager to display the manual feed alert
  122.  
  123.         do
  124.         {
  125.  
  126.             anErr = GXAlertTheUser(pStatus);
  127.  
  128.             // see if the user has loaded the paper
  129.  
  130.             if ((anErr == noErr) && (pStatus->dialogResult == nil)) {
  131.     
  132.                 Boolean    userFedPaper;    
  133.                 
  134.                 userFedPaper = CheckToSeeIfPaperWasFed();
  135.                 if (userFedPaper) {
  136.                     pStatus->statResIndex    = gxUnivPrinterReadyIndex;
  137.                     anErr = GXAlertTheUser(pStatus);
  138.                     pStatus->dialogResult = ok;
  139.                     
  140.                     }
  141.                 }
  142.                 
  143.             } while ((pStatus->dialogResult == nil) &&  (anErr == noErr));
  144.  
  145.  
  146. // act on the dialog result
  147.  
  148.         if (anErr == noErr) {
  149.         
  150.             switch (pStatus->dialogResult) {
  151.                 
  152.                 ok:                        PrintThePageManually();
  153.                                             break;
  154.                                 
  155.                 cancel:                    anErr = gxPrUserAbortErr;
  156.                                             break;
  157.                                 
  158.                 gxAutoFeedButtonId:    PrintThePageAutomatically();
  159.                                             break;
  160.                 }
  161.             }
  162.         DisposePtr( pStatus );
  163.         }
  164.     return( anErr );
  165. }
  166.  
  167.  
  168.  
  169. // Sample code for "Printer Not Responding" - one you do yourself
  170.  
  171. //
  172. //
  173. //        HandleOpenConnection
  174. //
  175. //        This function will attempt to open a connection to the printer.  If it fails
  176. //        it will send an alert to the user.
  177. //
  178. //        The driver supplies a 'cool' Alert resource.  The stat resource referenced by
  179. //        the status record that the driver builds will reference this cool alert.
  180. //        Note that the cool alert has place holders for strings.  The printing manager
  181. //        will fill these strings in with the name of the printer and the document. This
  182. //        is the default behavior when a cool alert is referenced with these placeholders.
  183. //        !0 will be replaced with the printer name.  !1 will be replaced with the document
  184. //        name.  !2 will be replaced with any papertype name sent.
  185. //
  186. //        The driver must allocate a status record with a default buffer that will be used
  187. //        internally by the printing manager.
  188. //
  189. //        The driver fills in the statResId and statResIndex fields of the status record
  190. //        to indicate that the desired stat resource belongs to the driver and
  191. //        the particular alert informs the user that the printer cannot be found.
  192. //
  193. //        The driver then calls GXAlertTheUser which will display the dialog.  The driver
  194. //        continues to call GXAlertTheUser until an error is returned or the user selects
  195. //        the Abort button.  The driver continues to look for the printer while the
  196. //        alert is up.  If the printer is found, the driver calls GXAlertTheUser a final
  197. //        time to remove the dialog.  If the user selects the Abort button, the dialog
  198. //        is automatically dismissed.   The dialog is also dismissed when any error is returned.
  199. //
  200. //        The driver examines the dialogResult field of the status record to see which
  201. //        option the user has selected.
  202. //
  203. //        Before exiting the routine, the status record pointer is disposed.
  204. //
  205. //        Note that the TryToOpenConnection routine must be supplied by the driver.
  206. //
  207. //
  208.  
  209. #define    kTransmissionStatID            1
  210. #define    kCantFindPrinterStatIdx        7
  211.  
  212.  
  213. OSErr    HandleOpenConnection()
  214. {
  215.     OSErr                anErr;
  216.     gxStatusRecord    *pStatus;    
  217.     
  218.     
  219.     anErr = TryToOpenConnection();
  220.  
  221.     if (anErr == gxAioCantFindDevice)             //    T => Can't locate device; tell user to turn it on
  222.     {
  223.         // Now we set-up to alert the user that the printer cannot be found
  224.         // Allocate a status record large enough to handle status with the largest 
  225.         // buffer size. 
  226.     
  227.         pStatus = (Ptr) NewPtrClear(sizeof(gxStatusRecord) + gxDefaultStatusBufferSize);
  228.         anErr = MemError();
  229.         if (anErr == noErr) {
  230.     
  231.             // Initialize the appropriate fields within the status record 
  232.             
  233.             pStatus->statResId         = kTransmissionStatID;
  234.             pStatus->statResIndex     = kCantFindPrinterStatIdx;
  235.             pStatus->bufferLen         = gxDefaultStatusBufferSize;
  236.     
  237.             // Now display the alert to the user
  238.             do
  239.             {    
  240.                 anErr = GXAlertTheUser(pStatus);
  241.                 if ((anErr == noErr) && (pStatus->dialogResult == nil))
  242.                 {                // Try looking for the device again
  243.                     anErr = TryToOpenConnection();
  244.                 }
  245.             }
  246.             while ( (anErr == gxAioCantFindDevice) && (pStatus->dialogResult == nil) );
  247.             
  248.             // If the user dismissed the dialog, we are to abort the job
  249.             if (pStatus->dialogResult != nil)
  250.                 anErr = gxPrUserAbortErr;
  251.             
  252.             else        // another error (possible timeout) or success
  253.             {
  254.                 pStatus->statResId      =    gxUnivAlertStatusResourceId;
  255.                 pStatus->statResIndex =    gxUnivPrinterReadyIndex;
  256.                 GXAlertTheUser(pStatus);     // Tell GX to remove the alert
  257.             }
  258.             
  259.             // Kill the status pointer
  260.             DisposPtr((Ptr) pStatus);
  261.             }
  262.     }
  263.     
  264.     return( anErr );
  265. }
  266.  
  267.  
  268. resource 'cool' (kCantFindPrinterCoolID, sysheap, purgeable)
  269. {                                                                    //    The printer can't be found on the 
  270.                                                                     //     SCSI bus
  271.     coolStatus,                                // version
  272.     cautionIcon,                            // icon id
  273.     defaultSystemSize,
  274.     defaultAction,                            // the default label
  275.     noCancelTitle,                            // no cancel
  276.     "The document !1 cannot be printed, because the printer "
  277.      "!0 cannot be found.  To continue printing, please make "
  278.     "sure the printer is "
  279.     "properly connected and turned on.  If you wish "    
  280.     "to cancel printing, please click Abort Job.",
  281.      "Abort Job",                                // action label
  282.     "",                                            // button label 2
  283.     "",                                            // button label 3
  284.     " "                                            // font name
  285. };
  286.  
  287.  
  288.  
  289. // Sample code for "Plotter Carousel Change" Alert - one you do yourself
  290.  
  291. //
  292. //
  293. //        HandleCarouselChange
  294. //
  295. //        This function will initiate a dialog with the user asking the user to
  296. //        place the appropriate carousel in the plotter.
  297. //
  298. //        The dialog that will be displayed to the user is not a cool alert.  The
  299. //        driver needs to supply parts of the dialog dynamically - the name of the
  300. //        carousel and the names of the pens it hopes to find there.  These names
  301. //        are stored in the buffer in the status record.  The driver allocates the
  302. //        status record with a buffer larger enough to hold these strings.  It then
  303. //        fills in the strings.
  304. //
  305. //        The driver fills in the statResId and statResIndex fields of the status record
  306. //        to indicate that the desired stat resource belongs to the driver and
  307. //        the particular alert informs the user that the print carousel needs to be changed.
  308. //
  309. //        The driver then calls GXAlertTheUser which will display the dialog.  The driver
  310. //        continues to call GXAlertTheUser until an error is returned or the user selects
  311. //        the Abort one of the buttons in the dialog.
  312. //
  313. //        In order to conduct this dialog, the driver must override 2 messages - 
  314. //            InitializeStatusAlert - to create the dialog and
  315. //            HandleAlertEvent         - to handle dialog events
  316. //
  317. //        The driver examines the dialogResult field of the status record to see which
  318. //        option the user has selected.
  319. //
  320. //        Before exiting the routine, the status record pointer is disposed.
  321. //
  322. //        Note that the FillInCarouselInfo routine must be supplied by the driver.
  323. //
  324. //
  325.  
  326. #define    kTransmissionStatID            1
  327. #define    kLoadPenIdx                        3
  328.  
  329. typedef struct {
  330.     Str31        carouselName;
  331.     Str15        penName1;                
  332.     Str15        penName2;                
  333.     Str15        penName3;                
  334.     Str15        penName4;                
  335.     } CarouselInfo;
  336.  
  337. OSErr    HandleCarouselChange()
  338. {
  339.     OSErr                anErr;
  340.     gxStatusRecord    *pStatus;    
  341.     
  342.     
  343.     // Allocate a status record large enough to handle status with the a
  344.     // buffer to hold the CarouselInfo structure. 
  345.  
  346.     pStatus = (Ptr) NewPtrClear(sizeof(gxStatusRecord) + sizeof( CarouselInfo ));
  347.     anErr = MemError();
  348.     if (anErr == noErr) {
  349.  
  350.  
  351.         // fill in the status buffer will carousel name and pen names
  352.         
  353.         FillInCarouselInfo( pStatus );
  354.     
  355.         // Initialize the appropriate fields within the status record 
  356.         
  357.         pStatus->statResId         = kTransmissionStatID;
  358.         pStatus->statResIndex     = kLoadPenIdx;
  359.         pStatus->bufferLen         = sizeof( CarouselInfo );
  360.  
  361.         // Now display the alert to the user
  362.         do
  363.         {    
  364.             anErr = GXAlertTheUser(pStatus);
  365.         }
  366.         while ( (anErr == noErr) && (pStatus->dialogResult == nil) );
  367.         
  368.         // Act on result
  369.  
  370.         if (pStatus->dialogResult != nil) {
  371.         
  372.             switch (pStatus->dialogResult)
  373.             
  374.             ok:                HandleChange();
  375.                                 break;
  376.  
  377.             cancel:            HandleCancel();
  378.                                 break;
  379.                                 
  380.             holdRequest:    HandleHold();
  381.                                 break;
  382.  
  383.             }
  384.         
  385.         // Kill the status pointer
  386.         DisposPtr((Ptr) pStatus);
  387.         }
  388.     
  389.     return( anErr );
  390. }
  391.  
  392.  
  393. //
  394. //        MyInitializeStatusAlert
  395. //
  396. // This routine is called when overriding InitializeStatusAlert
  397. //
  398. //    Since this is a message, the first thing the driver does is see if this
  399. // message is intended for the driver by checking the owner field in the
  400. // status record.  If the owner is not the driver, the message is forwarded.
  401. //
  402. // In the case that the driver is the owner, the driver checks the status id
  403. // to see which alert needs to be created.  The driver calls GetNewDialog on
  404. // the appropriate resource and then calls a routine to dynamically fill in
  405. // the static text strings in the dialog.  These strings are stored in the
  406. // status buffer in the status record.
  407. //
  408. // On the return, the Finder will display the dialog referenced through the
  409. // pDialog parameter.
  410. //
  411. //
  412.  
  413. OSErr    MyInitializeStatusAlert( gxStatusRecordPtr pStatus, DialogPtr *pDialog )
  414. {
  415.     OSErr        anErr = noErr;
  416.     
  417.     // first see if this message is for you
  418.     
  419.     if (pStatus->statusOwner == kDrvrCreatorType) {
  420.  
  421.         if (pStatus->statusId == kChangeCarouselsDlogID) {
  422.  
  423.             *pDialog = GetNewDialog( kChangeCarouselsDlogID, nil, (WindowPtr)-1);
  424.             if (*pDialog == nil)
  425.                 anErr = resNotFound;
  426.             else
  427.                 FillInDialogStrings( pStatus, pDialog );
  428.  
  429.  
  430.  
  431.             }
  432.         else...
  433.  
  434.  
  435.         }
  436.  
  437.     else                                                                    // it belongs to someone else
  438.         Forward_GXInitializeStatusAlert( pStatus, pDialog );
  439.         
  440.     return( anErr );
  441. }
  442.  
  443.  
  444. //
  445. //        MyHandleAlertEvent
  446. //
  447. // This routine is called when overriding HandleAlertEvent
  448. //
  449. //    Since this is a message, the first thing the driver does is see if this
  450. // message is intended for the driver by checking the owner field in the
  451. // status record.  If the owner is not the driver, the message is forwarded.
  452. //
  453. // In the case that the driver is the owner, the driver checks the status id
  454. // to see which alert is being conducted.  The driver then examines the event
  455. // for the alert.  If the user dismisses the dialog by selecting a dialog 
  456. // button, this result is recorded in the status record.
  457. //
  458. // On the return, the Finder will dismiss the dialog if the dialogResult field
  459. // is not nil.  The dialog is also dismissed when any error is returned.
  460. //
  461. // Note that a driver may use the status buffer for any purpose it needs to.  For
  462. // example, if the driver needed more information returned from this dialog, it
  463. // could be stored in the buffer.
  464. //
  465. // Note that the HandleCarouselDialogEvent is supplied by the driver.
  466. //
  467. //
  468. OSErr    MyHandleAlertEvent( gxStatusRecordPtr pStatus, DialogPtr *pDialog,
  469.                                   EventRecord *theEvent, short *itemHit )
  470. {
  471.     OSErr        anErr = noErr;
  472.     
  473.     // first see if this message is for you
  474.     
  475.     if (pStatus->statusOwner == kDrvrCreatorType) {
  476.  
  477.         if (pStatus->statusId == kChangeCarouselsDlogID) {
  478.  
  479.             HandleCarouselDialogEvent( pDialog, theEvent, itemHit );
  480.             pStatus->dialogResult = *itemHit;
  481.  
  482.  
  483.             }
  484.         else...
  485.  
  486.  
  487.         }
  488.  
  489.     else                                                // it belongs to someone else
  490.         Forward_GXHandleAlertEvent( pStatus, pDialog, theEvent, itemHit );
  491.         
  492.     return( anErr );
  493. }
  494.  
  495.  
  496. #define SystemSevenOrLater        true
  497.  
  498. resource 'DLOG' (kChangeCarouselsDlogID, sysheap, purgeable) {
  499.     {50, 10, 310, 440},
  500.     movableDBoxProc,
  501.     invisible,
  502.     noGoAway,
  503.     0x0,
  504.     kChangeCarouselsDlogID,
  505.     "",
  506.     centerMainScreen
  507. };
  508.  
  509.  
  510. resource 'DITL' (kChangeCarouselsDlogID, sysheap, purgeable) {
  511.     {    /* array DITLarray: 32 elements */
  512.         /* [1] */
  513.         {234, 335, 254, 415},
  514.         Button {
  515.             enabled,
  516.             "Continue"
  517.         },
  518.         /* [2] */
  519.         {234, 178, 254, 320},
  520.         Button {
  521.             enabled,
  522.             "Cancel print request"
  523.         },
  524.         /* [3] */
  525.         {234, 10, 254, 165},
  526.         Button {
  527.             enabled,
  528.             "Place request on Hold"
  529.         },
  530.         /* [4] */
  531.         {20, 60, 68, 410},
  532.         StaticText {
  533.             disabled,
  534.             "Please place the ^0 carousel in the plotter.  Make sure the "
  535.             "plotter is finished with the current set of pens before "
  536.             "making the change."
  537.         },
  538.         /* [5] */                    
  539.         {105, 30, 198, 207},            //    Rectangle that bounds the image of the carousel
  540.         UserItem {
  541.             disabled
  542.         },
  543.         /* [6] */
  544.         {90, 215, 106, 235},
  545.         StaticText {
  546.             enabled,
  547.             "1."
  548.         },
  549.         /* [7] */
  550.         {90, 240, 106, 400},        //    Pen #1 name
  551.         StaticText {
  552.             enabled,
  553.             ""
  554.         },
  555.         /* [8] */
  556.         {106, 215, 122, 235},
  557.         StaticText {
  558.             enabled,
  559.             "2."
  560.         },
  561.         /* [9] */
  562.         {106, 240, 122, 400},        //    Pen #2 name
  563.         StaticText {
  564.             enabled,
  565.             ""
  566.         },
  567.         /* [10] */
  568.         {122, 215, 138, 235},
  569.         StaticText {
  570.             enabled,
  571.             "3."
  572.         },
  573.         /* [11] */
  574.         {122, 240, 138, 400},        //    Pen #3 name
  575.         StaticText {
  576.             enabled,
  577.             ""
  578.         },
  579.         /* [12] */
  580.         {138, 215, 154, 235},
  581.         StaticText {
  582.             enabled,
  583.             "4."
  584.         },
  585.         /* [13] */
  586.         {138, 240, 154, 400},        //    Pen #4 name
  587.         StaticText {
  588.             enabled,
  589.             ""
  590.         },
  591.         /* [14] */
  592.         {20, 9, 52, 41},        //    Stop icon
  593.         Icon {
  594.             disabled,
  595.             2
  596.         },
  597.     }
  598. };
  599.  
  600.